/*
 * ***** BEGIN LICENSE BLOCK *****
 * This file is part of "myWiWall".
 * Copyright (c) 2007-2008 CRP Henri Tudor and contributors.
 * All rights reserved.
 *
 * "myWiWall" is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 * 
 * "myWiWall" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with "myWiWall"; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***** END LICENSE BLOCK *****
 */


	function WidgetContainer(id)
	{
		this.id = id;
		this.manifest;
		this.minimized;
		this.requiresSync;
		
		// Shortcuts to DOM Elements. Please feel free to add ones following your needs.
		this.widgetTitleContainer = null;
	}
	
	/* this method initializes the widget placeholder that gets replaced with the widget content later on */
	WidgetContainer.prototype.displayPlaceHolder = function()
	{
		/* global widget container */
		var widgetContainer = document.createElement('div');
		widgetContainer.id = 'widgetContainer_'+this.id;
		widgetContainer.className = 'widget_container';
		
		var placeholder = document.createElement('div');
		placeholder.id = 'placeholder_'+this.id;
		placeholder.className = 'placeholder';

		widgetContainer.appendChild(placeholder);
		
		return widgetContainer;
	}
	
	/* this method creates the widget content */
	WidgetContainer.prototype.init = function(manifest)
	{
		var thisInstance = this;
		
		this.manifest = manifest;
		
		/* widget title container */
		var widgetTitleContainer = document.createElement('div');
		this.widgetTitleContainer = widgetTitleContainer;
		widgetTitleContainer.id = 'widgetTitleContainer_'+this.id;
		widgetTitleContainer.className = 'widget_title_container';
		
		/* widget delete button */
		var widgetDeleteButton = document.createElement('a');
		widgetDeleteButton.href = '#';
		widgetDeleteButton.title = I18n.__("Remove");
		widgetDeleteButton.className = 'widget_delete_button';
		widgetDeleteButton.id = 'del_' + this.id;
		widgetDeleteButton.onclick = function (){
			if (confirm(I18n.__("Are you sure you want to remove this widget ?")))
			{
				// this.id refers to the id of the delete button
				widgetId = this.id.substr(4);
				
				/* synchronize with server */
				serial = $.SortSerialize(document.getElementById('widgetContainer_' + widgetId).parentNode.id);
				updateInterface(new Array(serial), 'delete', widgetId);
				
				/* remove from interface */
				$('#widgetContainer_' + widgetId).remove();
				delete widgetFactory.widgets[widgetId];
			}
		};
		
		$(widgetDeleteButton).bind('mousedown', function(event){
			event.stopPropagation();
		});
		
		/* widget minimize button */
		var widgetMinButton = document.createElement('a');
		widgetMinButton.href = '#';
		widgetMinButton.title = (this.minimized) ? I18n.__("Expand") : I18n.__("Collapse");
		widgetMinButton.className = (this.minimized) ? 'widget_max_button' : 'widget_min_button';
		widgetMinButton.id = 'min_' + this.id;
		
		$(widgetMinButton).bind('click', function(event){
			thisInstance.showHide();
		});

		$(widgetMinButton).bind('mousedown', function(event){
			event.stopPropagation();
		});
	
		/* widget maximize button (alternate url) */
		var widgetAltButton = document.createElement('a');
		widgetAltButton.href = this.manifest['alternate_url'];
		widgetAltButton.title = 'Goto alternate URL';
		widgetAltButton.target = '_blank';
		widgetAltButton.className = 'widget_alt_button';
		widgetAltButton.id = 'alt_' + this.id;
		
		$(widgetAltButton).bind('mousedown', function(event){
			event.stopPropagation();
		});

        /* widget email button */
        var widgetEmailButton = document.createElement('a');
        widgetEmailButton.href = 'mailto:'+this.manifest['author_email'];
        widgetEmailButton.title = I18n.__("Send an email to the Widget author");
        widgetEmailButton.className = 'widget_email_button';
        widgetEmailButton.id = 'email_' + this.id;
        
        $(widgetEmailButton).bind('mousedown', function(event){
			event.stopPropagation();
		});
		
		/* widget edit button */
		var widgetEditButton = document.createElement('a');
		widgetEditButton.href = '#';
		widgetEditButton.title = I18n.__("Edit");
		widgetEditButton.className = 'widget_edit_button';
		widgetEditButton.id = 'edit_' + this.id;
		widgetEditButton.onclick = function(){
			widgetId = this.id.substr(5);
			widgetFactory.widgets[widgetId].edit();
		}
		
		$(widgetEditButton).bind('mousedown', function(event){
			event.stopPropagation();
		});
		
		/* widget authentication icon */
		var widgetAuthImage = document.createElement('a');
		widgetAuthImage.className = 'widget_auth_button';
		widgetAuthImage.href = '#';
		widgetAuthImage.title = I18n.__("Widget Authentication Mechanism activated");
		
		/* widget title */
		var widgetTitle = document.createElement('span');
		widgetTitle.className = 'widget_title';
		widgetTitle.appendChild(document.createTextNode(this.manifest['widgetname']));
		
		var widgetControl = document.createElement('span');
		widgetControl.className = 'widget_control';
		
		widgetControl.appendChild(widgetDeleteButton);
		widgetControl.appendChild(widgetMinButton);
		
		/* only add alternate URL if available */
		if(this.manifest['alternate_url'])
		{
			widgetControl.appendChild(widgetAltButton);
		}
	
		if (this.manifest['author_email'])
		{
			widgetControl.appendChild(widgetEmailButton);
		}

		widgetControl.appendChild(widgetEditButton);
		
		/* Widget authentication image if needed. */
		if (this.manifest['widget_authentication'] == 'enabled')
			widgetControl.appendChild(widgetAuthImage);
		
		widgetTitleContainer.appendChild(widgetControl);
		
		/* widget icon */
		if(manifest['icon'])
		{
			if(manifest['icon'].substr(0,7) == 'http://')
				this.setIcon(manifest['icon'], true);
			else
				this.setIcon(manifest['icon'], false);
		}
		else
		{
			this.setIcon('../../views/common/misc/application.png', false);
		}
		
		
		widgetTitleContainer.appendChild(widgetTitle);
		
		/* iframe container */
		var iframeContainer = document.createElement('div');
		iframeContainer.id = 'iframeContainer_'+this.id;
		//iframeContainer.name = 'iframeContainer_'+this.id;
		iframeContainer.className = 'iframe_container';
		if (this.minimized)
			$(iframeContainer).toggle();
		
		/* iframe document */
		var iframe = document.createElement('iframe');
		iframe.id = 'iframe_'+this.id;
		iframe.name = 'iframe_'+this.id;
		
		var id = this.id;
		
		/* widget object injection management */
		if (jQuery.browser.msie)
		{
			iframe.onreadystatechange = function(){	
				if(this.readyState == 'interactive')
					widgetFactory.widgets[this.id.substr(7)].insertWidgetIntoContainer();
			};
		}
		else
		{		
			iframe.onload = function(){
			widgetFactory.widgets[this.id.substr(7)].insertWidgetIntoContainer();					
			};
		}	
		
		
		/* local vs. remote */
		if (this.manifest['widget_type'] == 'local')
		{
			//iframe.src = '../../widgets/' + this.id + '/index.html';
			var filename = (this.manifest['content_src']) ? encodeURIComponent(this.manifest['content_src']) : 'index.html';
			var locale = 'en'; // TODO Find a way to determine widget instance's locale.
			
			iframe.src = '../../widgets/' + this.manifest['id'] + '/' + filename;
		}
		else
		{
			var params = this.getRemotePreferences();
			iframe.src = this.manifest['widget_location']	+ '?' + params;
		}
		
		iframe.frameBorder = 0;
		iframe.setAttribute('scrolling', 'no');
		iframe.className = 'iframe';
		
		/* set the scrolling mode regarding manifest */
		if (this.manifest['scrollable'] == 'true')
			$(iframe).css('overflow-y', 'auto');

		/* set widget height from manifest */
		$(iframe).height(this.manifest['height']);
		$(iframeContainer).height(this.manifest['height']);
					
		iframeContainer.appendChild(iframe);
		
		/* create table layout */
		var layout = document.createElement('table');
		layout.id = 'wdg_' + this.id;
		layout.className = 'wdg';
		
		var tbody = document.createElement('tbody');
		layout.appendChild(tbody);
		
		for (var i=0; i<3; i++)
		{
			tbody.appendChild(document.createElement('tr'));
		}
	
		var cells = new Array('wdg_topleft', 'wdg_top', 'wdg_topright', 'wdg_left', 'wdg_content', 'wdg_right', 'wdg_bottomleft', 'wdg_bottom', 'wdg_bottomright');
		
		var t=0;
		for (i=0, t=0; i < cells.length; i++)
		{
			var node = document.createElement('td');
			node.className = cells[i];
	
			tbody.childNodes[t].appendChild(node);
			if (i%3 == 2)
				t++;
		}
		
		tbody.firstChild.childNodes[1].appendChild(widgetTitleContainer);
		tbody.childNodes[1].childNodes[1].appendChild(iframeContainer);

		$('#widgetContainer_'+this.id).empty();
		$('#widgetContainer_'+this.id).append(layout);
		$('#widgetContainer_'+this.id).height('100%');
		
		/* add drag and drop functionality */
		$('td.column').SortableAddItem(document.getElementById('widgetContainer_'+this.id));

		/* synchronize with server */
		if (this.requiresSync == true)
		{
			var serial = $.SortSerialize('c_0');
			updateInterface(new Array(serial), 'add', this.id);
		}
	}
	
	WidgetContainer.prototype.insertWidgetIntoContainer = function()
	{
		try 
		{
			var iframe = document.getElementById('iframe_'+this.id);
			iframe.opener = iframe;
			var doc = iframe.contentWindow || iframe.contentDocument;
			doc.parent = null;
			var auth = this.manifest['widget_authentication'] == 'enabled';		
			
			// Here is the only place we instantiate the widget object.
			// So if you have to deeply transform the widget constructor, feel
			// free to do it :D
			var options = {
				id: 				this.manifest['id'],
				title: 				this.manifest['widgetname'],
				height: 			this.manifest['height'],
				width:				this.manifest['width'],
				authorName:			this.manifest['author_name'],
				authorEmail:		this.manifest['author_email'],
				authorURL:			this.manifest['author_url'],
				description:		this.manifest['description'],
				useAuthentication:	auth,
				minimized:			this.minimized
			};
			
			// Create WidgetIcon for the Widget object creation.
			if (this.manifest['icon'])
			{
				var widgetIconParams = {
					src:	this.manifest['icon'],
					active:	true
				};
				
				options.icon = new WidgetIcon(widgetIconParams);
			}
			
			doc.widget = new Widget(options,
									eventDispatcher,
									dragManager);
									
			if (auth)
				doc.widget.enableAuthentication();

			for (i in this.manifest['preferences'])
			{
				doc.widget.setPreferenceForKey(this.manifest['preferences'][i]['name'], this.manifest['preferences'][i]['value'], false);
			}		
				
			if (doc.onLoad)
			{
				doc.onLoad();
			}
		} 
		catch (e)
		{
			debug('Unable to access iframe DOM.' + this.id);
			debug(e);
		}
	}
	
	WidgetContainer.prototype.edit = function()
	{
		/* hide the iframe */
		$('#iframe_'+this.id).toggle();
		
		/*  test if we are in edit mode */
		if (document.getElementById('editContainer_' + this.id))
		{
			var iframe = document.getElementById('iframe_'+this.id);
			iframe.opener = iframe;
			var doc = iframe.contentWindow || iframe.contentDocument;

			var height = 0;
			try {
				height = doc.widget.getHeight();
			} catch(e) {
				height = this.manifest['height'];
			}
			
			$('#iframeContainer_' + this.id).height(height);

			/* delete the edit container */
			document.getElementById('iframeContainer_' + this.id).removeChild(document.getElementById('editContainer_' + this.id));
		}
		else
		{
			$('#iframeContainer_' + this.id).height('auto');
		
			/* create the edit container */
			editContainer = document.createElement('div');
			editContainer.id = 'editContainer_' + this.id;
			editContainer.className = 'edit_container';
			
			/* create the edit form */
			editForm = document.createElement('form');
			editForm.id = 'editForm_' + this.id;
			editForm.className = 'edit_form';
			editForm.action = '#';
			
			editFieldSet = document.createElement('fieldset');
			
			editLegend = document.createElement('legend');
			editLegend.appendChild(document.createTextNode(I18n.__("Edit your preferences")));
			
			editFieldSet.appendChild(editLegend);
			
			/* create the form elements */
			for (i in this.manifest['preferences'])
			{
				pref = this.manifest['preferences'][i];
				
				if(pref['datatype'] == 'hidden')
					continue;
				
				pg = document.createElement('p');
				
				label = document.createElement('label');
				label.setAttribute('for', 'editForm_'+this.id+'_'+i);
				label.appendChild(document.createTextNode(pref['display_name'] + ': '));
				
				pg.appendChild(label);
				
				switch(pref['datatype'])
				{
					case 'string':
					case 'number':
						input = document.createElement('input');
						input.setAttribute('type', 'text');
						$(input).addClass('text');
						input.id = 'editForm_'+this.id+'_'+i;
						input.name = 'editForm_'+this.id+'_'+i;
						input.value = pref['value'];
						
						pg.appendChild(input);
						break;
					case 'bool':
						options = {0: false, 1: true};
						
					case 'enumeration':
						if (pref['datatype'] == 'enumeration')
							options = pref['values'];
						
						select = document.createElement('select');
						select.id = 'editForm_'+this.id+'_'+i;
						select.name = 'editForm_'+this.id+'_'+i;
						
						for (t in options)
						{
								var opt = document.createElement('option');
								opt.setAttribute('value', t);
								if(t == pref['value'])
								{
									opt.setAttribute('selected', true);
								}
								
								opt.appendChild(document.createTextNode(options[t]));
								select.appendChild(opt);
						}
						pg.appendChild(select);
						break;
				}
				editFieldSet.appendChild(pg);
			}
			
			pg = document.createElement('p');
								
			/* Tags Label */
			tagLabel = document.createElement('label');
			tagLabel.setAttribute('for', 'tagInput_'+this.id);
			tagLabel.appendChild(document.createTextNode('Tags: '));
			tagLabel = pg.appendChild(tagLabel);
			
			/* Tags Input Field */
			tagInput = document.createElement('input');
			tagInput.setAttribute('type', 'text');
			tagInput.className = 'text';
			tagInput.id = 'tagInput_'+this.id;
			tagInput.name = 'tagInput_' + this.id;
			tagInput = pg.appendChild(tagInput);
			
			tags = document.createElement('div');
			tags.id = 'tags_'+this.id;
			tags.className = 'widget_tags';
			tags = pg.appendChild(tags);
			
			pg = editFieldSet.appendChild(pg);
			
			/* edit submit button */
			editButton = document.createElement('input');
			editButton.type = 'submit';
			editButton.value = I18n.__("Save");
			editButton.id = 'editButton_' + this.id;
			editButton.className = 'button';
			editButton.onclick = function(){
				/* updatPreferences in engine.js */
				updatePreferences(this.id.substr(11));
				return false;
			}

			editFieldSet.appendChild(editButton);
			
			/* edit cancel button */
			editCancelButton = document.createElement('input');
			editCancelButton.type = 'reset';
			editCancelButton.value = I18n.__("Cancel");
			editCancelButton.id = 'editCancelButton_' + this.id;
			editCancelButton.className = 'button';
			editCancelButton.onclick = function(){
				/* call the edit method again */
				widgetId = this.id.substr(17);
				widgetFactory.widgets[widgetId].edit();
				return false;
			}
			
			editFieldSet.appendChild(editCancelButton);
			
			editForm.appendChild(editFieldSet);
			editContainer.appendChild(editForm);
			
			document.getElementById('iframeContainer_' + this.id).appendChild(editContainer);
			
			/* load the existing tags for this widget */
			$.getJSON('../../index.php/engine/getTags', {widget: this.id}, function(json){
				$('#tags_'+json['widget']).append(I18n.__("Current tags") + json['tags']);
			});
			
			/* add the autocomplete feature to the tagInput field */
			$('#tagInput_'+this.id).autocomplete('../../index.php/engine/getTags', {
				minChars:1,
				matchSubset:1,
				matchContains:1,
				cacheLength:10,
				selectOnly:1,
				mode:"multiple",
				multipleSeparator:" "
			});
		}
	}
	
	WidgetContainer.prototype.updateTitle = function(title)
	{
		$('#widgetTitleContainer_'+this.id+' .widget_title').empty();
		$('#widgetTitleContainer_'+this.id+' .widget_title').append(title);
	}
	
	WidgetContainer.prototype.updateHeight = function(height)
	{
		$('#iframeContainer_'+this.id).height(height);
		$('#iframe_'+this.id).height(height);			
	}	
	
	/* this method creates the GET arguments that we append to the remote widget URL */
	WidgetContainer.prototype.getRemotePreferences = function()
	{
		var params = '';
		for (i in this.manifest['preferences'])
		{
			params += '&' + encodeURIComponent(this.manifest['preferences'][i]['name']) + '=' + encodeURIComponent(this.manifest['preferences'][i]['value']);
		}
		params = params.substr(1);
		return params;
	}
	
	WidgetContainer.prototype.showHide = function()
	{
		// this.id refers to the id of the min button
		var widgetId = this.id;
		var widgetMinButton = $('#min_' + this.id).get(0);
		
		/* synchronize with server */
		updateInterface(null, 'minimize', widgetId);
		
		/* update user interface */
		widgetMinButton.className = (widgetMinButton.className == 'widget_min_button') ? 'widget_max_button' : 'widget_min_button';
		widgetMinButton.title = (this.className == 'widget_min_button') ? I18n.__("Collapse") : I18n.__("Expand");

		$('#iframeContainer_'+widgetId).toggle();

		if (this.manifest['widget_type'] == 'local')
		{
			
			var iFrame 		= $('#iframeContainer_' + widgetId).find('.iframe').get(0);
			var innerDoc 	= iFrame.contentWindow || iFrame.contentDocument;
			
			if (innerDoc.onResize)
				innerDoc.onResize((widgetMinButton.className == 'widget_min_button') ? 'maximize' : 'minimize');
		}
			
		/* Notify the event */
		var eventType = (widgetMinButton.className == 'widget_min_button') ? EventDispatcher.EVENT_WIDGET_MAXIMIZED : EventDispatcher.EVENT_WIDGET_MINIMIZED;
		
		eventDispatcher.fireWidgetEvent(EventDispatcher.EVENT_SOURCE_PORTAL, 
										eventType,
										{widgetId: widgetId},
										null);	
	}
	
	WidgetContainer.prototype.setAttention = function()
	{
		var widgetContainerElement = $('#wdg_' + this.id);

		if (widgetContainerElement.length > 0)
		{
			widgetContainerElement.addClass('get_attention');		
			window.setTimeout (function () { widgetContainerElement.removeClass('get_attention'); }, 1000);
		}
	}
	
	WidgetContainer.prototype.setIcon = function (src, fromWeb)
	{
		var widgetIconElement = document.createElement('img');
		widgetIconElement.className = 'widget_icon';
		
		var srcPrefix = '';
		if (!fromWeb)
		{
			// prevent errors by removing the first slash if needed.
			if (src.charAt(0) == '/')
				src = src.substr(1, src.length - 1);
				
			srcPrefix = '../../widgets/' + this.id + '/';
		}
		
		widgetIconElement.src = srcPrefix + src;
		
		$(this.widgetTitleContainer).append(widgetIconElement);
	}
